import { Provide, Inject } from '@midwayjs/core';
import { Context } from '@midwayjs/koa';
import { InjectEntityModel } from "@midwayjs/typeorm";
import { Like, Repository } from "typeorm";
import { User as NormalEntity } from "@entity/framework/system/SysUser";
import { SysRole as RoleEntity } from "@entity/framework/system/SysRole";
import { resBuild } from "@utils/resBuild";
import { SysDept } from '@entity/framework/system/SysDept';
import { StudentEntity } from '@entity/user/student.entity';
import { TeacherEntity } from '@entity/teacher.entity';
import { TeamEntity } from '@entity/team.entity';

// role中加入admin字段、断言，这时多出来的返回给前端字段
interface RoleEntityWithAdmin extends RoleEntity {
  admin?: boolean;
}
// user中加入admin字段、断言，这时多出来的返回给前端字段
interface UserEntityWithAdmin extends NormalEntity {
  admin?: boolean;
}

/** 获取基本的用户信息 */
@Provide()
export class UserInfoService {

  @Inject()
  ctx: Context;

  @InjectEntityModel(NormalEntity)
  protected dynamicModel: Repository<NormalEntity>;
  @InjectEntityModel(SysDept)
  protected deptModel: Repository<SysDept>;
  @InjectEntityModel(StudentEntity)
  protected studentModel: Repository<StudentEntity>;
  @InjectEntityModel(TeacherEntity)
  protected teacherModel: Repository<TeacherEntity>;
  @InjectEntityModel(TeamEntity)
  protected teamModel: Repository<TeamEntity>;



  // 查询用户信息
  async getUserInfo() {
    const userId = this.ctx.session.userInfo.userId;
    if (userId) {
      let userInfo: UserEntityWithAdmin = await this.dynamicModel.findOne({
        where: {
          userId: userId
        },
        relations: ['dept', 'roles', 'roles.menus']
      })

      // 如果查询到用户信息，稍微处理格式、然后返回用户信息
      if (userInfo) {
        // 角色列表
        const roles = [];
        userInfo.roles.forEach((role: RoleEntityWithAdmin) => {
          roles.push(role.roleKey);
          role.admin = role.roleKey === 'admin';
        })

        // 是否为超管
        const isAdmin = roles.includes('admin')
        userInfo.admin = isAdmin;

        // 权限列表
        let permissions = []

        // 如果是超管，拥有所有权限，处理roles格式返回给前端
        if (isAdmin) {
          permissions = ['*:*:*'];
        } else {
          userInfo.roles.forEach((role: RoleEntityWithAdmin) => {
            role.menus.forEach((menu) => {
              permissions.push(menu.perms)
            })
          })
        }
        this.ctx.session.permissions = permissions;
        return resBuild.more({
          user: userInfo,
          roles,
          permissions
        })
      }
    } else {
      throw new Error('用户信息不存在')
    }
  }
  // 获取系统信息
  async getSystemInfo() {
    const deptCount = await this.deptModel.count({
      where: {
        deptName: Like(`%学院%`)
      }
    });
    const studentCount = await this.studentModel.count();
    const teacherCount = await this.teacherModel.count();
    return resBuild.data({
      deptCount,
      studentCount,
      teacherCount
    })
  }
  // 获取系统列表
  async getSystemList() {
    // 计算7天前的日期（从今天开始往前推7天）
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const sevenDaysAgo = new Date(today);
    sevenDaysAgo.setDate(today.getDate() - 6); // 包含今天共7天
    const [
      studentTotal,
      teacherTotal,
      teamTotal,
      teamSelectedTotal,
      studentDaily,
      teacherDaily,
      teamDaily,
      collegeCount
    ] = await Promise.all([
      // 学生总数
      this.studentModel.count(),

      // 教师总数
      this.teacherModel.count(),

      // 队伍总数
      this.teamModel.count( {
        where: {
          delFlag: '0'
        }
      }),
      // select_flag为1的队伍总数
      this.teamModel.count({
        where: {
          selectFlag: '1',
          delFlag: '0'
        }
      }),
      this.getDailyCount(this.studentModel, 'student', sevenDaysAgo),

      // 近7天每日教师新增数
      this.getDailyCount(this.teacherModel, 'teacher', sevenDaysAgo),

      // 近7天每日队伍新增数
      this.getDailyCount(this.teamModel, 'team', sevenDaysAgo),
      // 学院总数
      this.deptModel.count({
        where: {
          deptName: Like(`%学院%`)
        }
      })
    ]);

    // 合并每日数据
    const recentSevenDays = this.mergeDailyData(
      studentDaily,
      teacherDaily,
      teamDaily
    );

    return {
      studentTotal,
      teacherTotal,
      teamTotal,
      teamSelectedTotal,
      recentSevenDays,
      collegeCount
    };
  }
   private async getDailyCount(
      repository: Repository<any>,
      tableName: string,
      startDate: Date
    ): Promise<{ date: string; count: number }[]> {
      // PostgreSQL使用TO_CHAR函数进行日期格式化
      const result = await repository
        .createQueryBuilder(tableName)
        .select("TO_CHAR(create_time, 'YYYY-MM-DD')", 'date')
        .addSelect('COUNT(*)', 'count')
        .where('create_time >= :startDate', { startDate })
        .groupBy('date')
        .orderBy('date', 'ASC')
        .getRawMany();

      return result.map(item => ({
        date: item.date,
        count: parseInt(item.count, 10)
      }));
    }

    /**
     * 合并三个表的每日数据
     */
    private mergeDailyData(
      studentDaily: { date: string; count: number }[],
      teacherDaily: { date: string; count: number }[],
      teamDaily: { date: string; count: number }[]
    ) {
      // 生成过去7天的日期列表
      const dates: string[] = [];
      const today = new Date();
      today.setHours(0, 0, 0, 0);

      for (let i = 6; i >= 0; i--) {
        const date = new Date(today);
        date.setDate(today.getDate() - i);
        dates.push(this.formatDate(date));
      }

      // 将数组转换为Map便于查找
      const studentMap = new Map(studentDaily.map(item => [item.date, item.count]));
      const teacherMap = new Map(teacherDaily.map(item => [item.date, item.count]));
      const teamMap = new Map(teamDaily.map(item => [item.date, item.count]));

      // 组装完整的7天数据（没有数据的日期填0）
      return dates.map(date => ({
        date,
        studentCount: studentMap.get(date) || 0,
        teacherCount: teacherMap.get(date) || 0,
        teamCount: teamMap.get(date) || 0
      }));
    }

    /**
     * 格式化日期为 YYYY-MM-DD
     */
    private formatDate(date: Date): string {
      const year = date.getFullYear();
      const month = String(date.getMonth() + 1).padStart(2, '0');
      const day = String(date.getDate()).padStart(2, '0');
      return `${year}-${month}-${day}`;
    }
  }
